package hyl.ext.ws.msg;

import hyl.core.AIni;
import hyl.core.MyFun;
import hyl.core.fun.MyByte;

/**
 * 
 * 消息包对象 用来封装 底层消息
 * 
 * 这是一类包 类似Netpg1 自带包头
 * 
 * 支持语音 视频等二进制流
 * 
 * 使用改消息结构时 所有传输数据必须使用二进制流传输
 * 
 * 相关程序只能 传输二进制流 不能传输文本
 * 
 * 
 * @author 37798955@qq.com
 *
 */
public class Msgpg implements Cloneable {
	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}

	// 系统消息无需中转 直接从服务端发给客户端
	public static final byte DC系统消息 = 0;
	// 用户消息需要中转,无法中转时 存储到服务端,用户上线后重新发送给用户所在的客户端
	public static final byte DC中转消息 = 1;

	public static final byte DC作废消息 = 4;
	// 不要用map 固然灵活 但是灵活也就意味的缺少规范,规则总是在变动, 思路愈加混乱,

	public byte 类型 = DC中转消息; 
	public String 发送方 = null; // null
	public String 接收方; // 必填
	public String 主题 = null; // 必填
	public String 字符串 = null; // 子主题
	public String 时间 = null;
	public byte[] 字节串;
	protected int 包数据长度 = 0;
	//这个构造函数只能 内部使用
	Msgpg() {
	}
	//用户使用必须指定消息的类型,否则系统会出错
	public Msgpg(byte 类型) {
		this.类型 = 类型;
	}

	public static Msgpg create消息(String 发送方, byte 类型) {
		Msgpg wmp = new Msgpg(类型);
		wmp.set发送方(发送方);
		return wmp;
	}

	public static Msgpg create中转消息() {
		Msgpg wmp = new Msgpg();
		return wmp;
	}
	public static Msgpg create系统消息(String 发送方) {
		Msgpg wmp = new Msgpg(DC系统消息);
		wmp.set发送方(发送方);
		return wmp;
	}

	public void clear() {
		类型 = DC中转消息; // 0 系统消息 1用户消息
		发送方 = null; // null
		接收方 = null; // 必填
		主题 = null; // 必填
		字符串 = null; // 子主题
		时间 = null;
		this.字节串 = null;
		包数据长度 = 0;
	}

	public void set发送方(String 发送方) {
		this.发送方 = 发送方;
	}

	public void setMsg(String 接收方, String 主题, String 文本) {
		this.接收方 = 接收方;
		this.主题 = 主题;
		this.字符串 = 文本;
		this.时间 = MyFun.isBlank(时间) ? MyFun.getNow() : 时间;
	}

	public void setMsg(String 接收方, String 主题, byte[] 内容) {
		setMsg(接收方, 主题, 内容, MyFun.getNow());
	}

	public void setMsg(String 接收方, String 主题, byte[] 内容, String 时间) {
		this.接收方 = 接收方;
		this.主题 = 主题;
		this.字节串 = 内容;
		this.时间 = MyFun.isBlank(时间) ? MyFun.getNow() : 时间;
	}

	public void setMsg(String 接收方, String 主题, String 文本, byte[] 内容) {
		setMsg(接收方, 主题, 文本, 内容, MyFun.getNow());
	}

	public void setMsg(String 接收方, String 主题, String 文本, byte[] 内容, String 时间) {
		this.接收方 = 接收方;
		this.主题 = 主题;
		this.字符串 = 文本;
		this.字节串 = 内容;
		this.时间 = MyFun.isBlank(时间) ? MyFun.getNow() : 时间;
	}

	/**
	 * 返回编译的字节
	 * 
	 * @return
	 */
	public byte[] toSendBytes() {
		int i[] = new int[6];
		byte[] b0 = new byte[] { this.类型 };
		byte[] b1 = MyFun.str2Bytes(发送方, AIni.charset);
		byte[] b2 = MyFun.str2Bytes(接收方, AIni.charset);
		byte[] b3 = MyFun.str2Bytes(主题, AIni.charset);
		byte[] b4 = MyFun.str2Bytes(字符串, AIni.charset);
		byte[] b5 = MyFun.str2Bytes(时间, AIni.charset);
		i[0] = (b1 == null ? 0 : b1.length);
		i[1] = (b2 == null ? 0 : b2.length);
		i[2] = (b3 == null ? 0 : b3.length);
		i[3] = (b4 == null ? 0 : b4.length);
		i[4] = (b5 == null ? 0 : b5.length);
		i[5] = (字节串 == null ? 0 : 字节串.length);
		包数据长度 = 4 * 6 + 1 + i[0] + i[1] + i[2] + i[3] + i[4] + i[5]; // 除i[0]以外 剩余数据的长度
		return MyFun.concat(MyFun.int2ByteArray(包数据长度), b0, MyFun.int2ByteArray(i[0]), //
				MyFun.int2ByteArray(i[1]), MyFun.int2ByteArray(i[2]), //
				MyFun.int2ByteArray(i[3]), MyFun.int2ByteArray(i[4]), //
				b1, b2, b3, b4, b5, 字节串);

	}

	/**
	 * 
	 * @param 缓冲区
	 * @return 返回 false 表示未结束 true 表示结束了
	 */
	public void ini(byte[] 缓冲区 ) {
		
		if (缓冲区 == null || 缓冲区.length == 0) {
			包数据长度 = 0;
			return;
		}
		if (4 > 缓冲区.length) {
			包数据长度 = 0;
			return;
		}
		包数据长度 = MyByte.bytes2int(缓冲区, 0);
		//MyFun.print(缓冲区.length,包数据长度);
		if (包数据长度 > 缓冲区.length) {
			包数据长度 = 0;
			return;
		}
		int i[] = new int[5];
		类型 = 缓冲区[4];
		int start = 5;
		for (int j = 0; j < 5; j++) {
			i[j] = MyByte.bytes2int(缓冲区, start);
			start += 4;
		}
		发送方 = MyFun.bytes2U8str(MyByte.subBytes(缓冲区, start, i[0]));
		start += i[0];
		接收方 = MyFun.bytes2U8str(MyByte.subBytes(缓冲区, start, i[1]));
		start += i[1];
		主题 = MyFun.bytes2U8str(MyByte.subBytes(缓冲区, start, i[2]));
		start += i[2];
		字符串 = MyFun.bytes2U8str(MyByte.subBytes(缓冲区, start, i[3]));
		start += i[3];
		时间 = MyFun.bytes2U8str(MyByte.subBytes(缓冲区, start, i[4]));
		start += i[4];
		int i5 = 包数据长度 - start;
		//MyFun.print(缓冲区.length,包数据长度,i5);
		字节串 = MyByte.subBytes(缓冲区, start, i5);
	}

	/**
	 * 包数据=包头(4字节)+包长度
	 * 
	 * @return
	 */
	public int length() {
		return 包数据长度;
	}

}
